﻿using AJWPFAdmin.Core.Excel;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Utils;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using Masuit.Tools;
using Masuit.Tools.Reflection;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace AJWPFAdmin.Core.Excel
{
    public class AJImport
    {
        private static readonly string[] _excelFileExts = new string[] { ".xls", ".xlsx" };

        private static string _excelFile;

        public static List<AJImportHeader> GetHeaders<T>()
        {
            var result = new List<AJImportHeader>();

            var props = typeof(T).GetRuntimeProperties();

            foreach (var item in props)
            {
                var attr = item.GetCustomAttribute<AJImportFieldAttribute>();
                if (attr == null)
                {
                    continue;
                }
                result.Add(new AJImportHeader
                {
                    Column = item.Name,
                    Title = attr.ColumnName,
                    Index = attr.ColumnIndex
                });
            }

            return result.OrderBy(p => p.Index).ToList();
        }

        public static List<AJImportHeader> GetHeaders(Type entityType)
        {
            var result = new List<AJImportHeader>();

            var props = entityType.GetRuntimeProperties();

            foreach (var item in props)
            {
                var attr = item.GetCustomAttribute<AJImportFieldAttribute>();
                if (attr == null)
                {
                    continue;
                }
                result.Add(new AJImportHeader
                {
                    Column = item.Name,
                    Title = attr.ColumnName,
                    Index = attr.ColumnIndex
                });
            }

            return result.OrderBy(p => p.Index).ToList();
        }

        public static AJImportTemplate CreateTemplate<T>(ICollection<T> samples)
        {
            var template = new AJImportTemplate();

            if (samples == null || samples.Count == 0)
            {
                return template;
            }

            template.Headers = GetHeaders<T>();

            foreach (var row in samples)
            {
                var rowProps = row.GetType().GetRuntimeProperties();
                var columnFields = new Dictionary<string, string>();
                foreach (var header in template.Headers)
                {
                    var prop = rowProps.FirstOrDefault(p => p.Name == header.Column);
                    if (prop == null)
                    {
                        continue;
                    }

                    var val = "";

                    var rawValue = prop.GetValue(row);
                    if (rawValue is DateTime)
                    {
                        val = ((DateTime)rawValue).ToString("yyyy-MM-dd");
                    }
                    else if (rawValue is DateTime?)
                    {
                        var nullableDate = rawValue as DateTime?;
                        val = nullableDate.HasValue
                            ? nullableDate.GetValueOrDefault().ToString("yyyy-MM-dd")
                            : "";
                    }
                    else if (rawValue is bool)
                    {
                        val = "是或否";
                    }
                    else if (rawValue is Enum)
                    {
                        var enumValues = Enum.GetValues(rawValue.GetType());
                        var enumStr = new List<string>();
                        foreach (var enumValue in enumValues)
                        {
                            enumStr.Add(enumValue.ToString());
                        }
                        val = string.Join("或", enumStr);
                    }
                    else
                    {
                        val = rawValue.ToString();
                    }

                    columnFields.Add(header.Title, val);
                }

                template.Rows.Add(columnFields);
            }

            return template;
        }

        public static AJImportTemplate CreateTemplate(Type entityType, ICollection<object> samples)
        {
            var template = new AJImportTemplate();

            template.Headers = GetHeaders(entityType);

            if (samples == null || samples.Count == 0)
            {
                return template;
            }

            foreach (var row in samples)
            {
                var rowProps = row.GetType().GetRuntimeProperties();
                var columnFields = new Dictionary<string, string>();
                foreach (var header in template.Headers)
                {
                    var prop = rowProps.FirstOrDefault(p => p.Name == header.Column);
                    if (prop == null)
                    {
                        continue;
                    }

                    var val = "";

                    var rawValue = prop.GetValue(row);
                    if (rawValue is DateTime)
                    {
                        val = ((DateTime)rawValue).ToString("yyyy-MM-dd");
                    }
                    else if (rawValue is DateTime?)
                    {
                        var nullableDate = rawValue as DateTime?;
                        val = nullableDate.HasValue
                            ? nullableDate.GetValueOrDefault().ToString("yyyy-MM-dd")
                            : "";
                    }
                    else if (rawValue is bool)
                    {
                        val = "是或否";
                    }
                    else if (rawValue is Enum)
                    {
                        var enumValues = Enum.GetValues(rawValue.GetType());
                        var enumStr = new List<string>();
                        foreach (var enumValue in enumValues)
                        {
                            enumStr.Add(enumValue.ToString());
                        }
                        val = string.Join("或", enumStr);
                    }
                    else
                    {
                        val = rawValue.ToString();
                    }

                    columnFields.Add(header.Title, val);
                }

                template.Rows.Add(columnFields);
            }

            return template;
        }

        /// <summary>
        /// 将excel转换成实体列表 T , ProcessResult.Data 就是  List<T>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="localexcelFile"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static ProcessResult LoadExcel<T>(string localexcelFile, int max = 1000) where T : class, new()
        {
            _excelFile = localexcelFile;
            var result = new ProcessResult();

            try
            {
                if (!_excelFileExts.Contains(Path.GetExtension(localexcelFile)))
                {
                    result.SetError("不是正确的excel文件");
                    return result;
                }
                var workbook = new XLWorkbook(localexcelFile);

                var sheet = workbook.Worksheets.FirstOrDefault();

                if (sheet == null)
                {
                    result.SetError("excel文件未包含任何数据表");
                    return result;
                }

                // 获得模板标题数据
                var headers = GetHeaders<T>();

                var lastCellUsed = sheet.LastCellUsed();

                var titleCells = sheet.Range(sheet.Cell(1, 1).Address,
                    sheet.Cell(1, headers.Count).Address).Cells().ToList();

                var newHeaders = new List<AJImportHeader>();
                // 检测标题行
                var index = 1;
                foreach (var titleCell in titleCells)
                {
                    var titleText = titleCell.Value.ToString();

                    var hd = headers.FirstOrDefault(p => p.Title == titleText);

                    if (hd == null)
                    {
                        result.SetError($"{titleText} 不在模板配置中");
                        return result;
                    }
                    newHeaders.Add(hd);
                    index++;
                }

                var list = new List<T>();

                var dataRows = sheet.Range(sheet.Cell(2, 1).Address, lastCellUsed.Address);

                //循环行,获得数据
                var count = dataRows.RowCount();

                if (count == 0)
                {
                    result.SetError("数据表不存在任何行");
                    return result;
                }

                if (count > max)
                {
                    result.SetError($"超过最大限制行数:{max}");
                    return result;
                }
                var cellCount = newHeaders.Count();

                for (int i = 1; i <= count; i++)
                {
                    var obj = new T();

                    var props = typeof(T).GetRuntimeProperties().OrderBy(p => p.Name).ToList();

                    for (int j = 1; j <= cellCount; j++)
                    {
                        var prop = props.FirstOrDefault(p => p.Name == newHeaders[j - 1].Column);
                        if (prop == null)
                        {
                            continue;
                        }

                        var propType = prop.PropertyType;

                        var cellValue = dataRows.Cell(i, j).Value.ToString();

                        if (!string.IsNullOrWhiteSpace(cellValue))
                        {
                            if (cellValue == "是" || cellValue == "否")
                            {
                                cellValue = cellValue == "是" ? "True" : "False";
                            }
                        }

                        if (propType.IsEnum)
                        {
                            if (Enum.TryParse(propType, cellValue, out var enumVal))
                            {
                                prop.SetValue(obj, enumVal);
                                continue;
                            }
                        }

                        if (cellValue.TryConvertTo(propType, out object proVal))
                        {
                            prop.SetValue(obj, proVal);
                        }
                        else
                        {
                            result.SetError($"第{i}行,{newHeaders[j].Column}:数据错误");
                            return result;
                        }
                    }

                    list.Add(obj);
                }

                result.SetSuccess(list);

            }
            catch (Exception e)
            {
                //Util.Util.Log4Logger.Error($"加载Excel文件失败:{localexcelFile}", e);
                result.SetError($"加载Excel文件失败:{e.Message}");
            }

            return result;
        }

        /// <summary>
        /// 将excel转换成实体列表 entityType , ProcessResult.Data 就是  List<entityType>
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="localexcelFile"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static ProcessResult LoadExcel(Type entityType, string localexcelFile, int max = 1000)
        {
            _excelFile = localexcelFile;
            var result = new ProcessResult();

            try
            {
                if (!_excelFileExts.Contains(Path.GetExtension(localexcelFile)))
                {
                    result.SetError("不是正确的excel文件");
                    return result;
                }
                var workbook = new XLWorkbook(localexcelFile);

                var sheet = workbook.Worksheets.FirstOrDefault();

                if (sheet == null)
                {
                    result.SetError("excel文件未包含任何数据表");
                    return result;
                }

                // 获得模板标题数据
                var headers = GetHeaders(entityType);

                var lastCellUsed = sheet.LastCellUsed();

                var titleCells = sheet.Range(sheet.Cell(1, 1).Address,
                    sheet.Cell(1, headers.Count).Address).Cells().ToList();

                var newHeaders = new List<AJImportHeader>();
                // 检测标题行
                var index = 1;
                foreach (var titleCell in titleCells)
                {
                    var titleText = titleCell.Value.ToString();

                    var hd = headers.FirstOrDefault(p => p.Title == titleText);

                    if (hd == null)
                    {
                        result.SetError($"{titleText} 不在模板配置中");
                        return result;
                    }
                    newHeaders.Add(hd);
                    index++;
                }

                var list = new List<object>();

                var dataRows = sheet.Range(sheet.Cell(2, 1).Address, lastCellUsed.Address);

                //循环行,获得数据
                var count = dataRows.RowCount();

                if (count == 0)
                {
                    result.SetError("数据表不存在任何行");
                    return result;
                }

                if (count > max)
                {
                    result.SetError($"超过最大限制行数:{max}");
                    return result;
                }
                var cellCount = newHeaders.Count();

                for (int i = 1; i <= count; i++)
                {
                    var obj = Activator.CreateInstance(entityType);

                    var props = entityType.GetRuntimeProperties().OrderBy(p => p.Name).ToList();

                    for (int j = 1; j <= cellCount; j++)
                    {
                        var prop = props.FirstOrDefault(p => p.Name == newHeaders[j - 1].Column);
                        if (prop == null)
                        {
                            continue;
                        }

                        var propType = prop.PropertyType;

                        var cellValue = dataRows.Cell(i, j).Value.ToString();

                        if (!string.IsNullOrWhiteSpace(cellValue))
                        {
                            if (cellValue == "是" || cellValue == "否")
                            {
                                cellValue = cellValue == "是" ? "True" : "False";
                            }
                        }

                        if (propType.IsEnum)
                        {
                            if (Enum.TryParse(propType, cellValue, out var enumVal))
                            {
                                prop.SetValue(obj, enumVal);
                                continue;
                            }
                        }

                        if (cellValue.TryConvertTo(propType, out object proVal))
                        {
                            prop.SetValue(obj, proVal);
                        }
                        else
                        {
                            result.SetError($"第{i}行,{newHeaders[j].Column}:数据错误");
                            return result;
                        }
                    }

                    list.Add(obj);
                }

                result.SetSuccess(list);

            }
            catch (Exception e)
            {
                //Util.Util.Log4Logger.Error($"加载Excel文件失败:{localexcelFile}", e);
                result.SetError($"加载Excel文件失败:{e.Message}");
            }

            return result;
        }

        //public static void DeleteExcel()
        //{
        //    if (string.IsNullOrWhiteSpace(_excelFile))
        //    {
        //        return;
        //    }

        //    //CommonUtil.TryDeleteFiles("", _excelFile);

        //    _excelFile = "";
        //}
    }
}
